import base64
import pickle
from django.shortcuts import render
from django_redis import get_redis_connection
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
from cart import constants
from cart.serializers import CartSerializer, CartGoodSerializer, CartDelSerializer
from goods.models import Goods


# Create your views here.


# url:/cart
class CartView(APIView):
    permission_classes = [IsAuthenticated]

    # def perform_authentication(self, request):
    #     """跳过DRF框架的认证过程"""
    #     pass

    # POST /cart/
    def post(self, request):
        """
        添加购物车数据
        1. 获取参数并进行校验（参数完整性，goods_id对应商品是否存在，count是否大于商品库存）
        2.保存用户的购物车记录
          2.1 如果用户已登录，在redis中保存登录用户的购物车记录
          2.2 如果用户未登录，在cookie中保存未登录用户的购物车记录
        3.返回应答，购物车记录添加成功
        """
        # 1. 获取参数并进行校验（参数完整性，goods_id对应商品是否存在，count是否大于商品库存）
        serializer = CartSerializer(data=request.data)

        serializer.is_valid(raise_exception=True)
        # 获取数据
        goods_id = serializer.validated_data['goods_id']

        count = serializer.validated_data['count']

        # selected = serializer.validated_data['selected']

        # 获取用户
        try:
            user = request.user

        except Exception:

            user = None

        # 2.保存用户的购物车记录
        # if user and user.is_authenticated:
        # 2.1 如果用户已登录，在re获取redis_conndis中保存登录用户的购物车记录
        #
        redis_conn = get_redis_connection('cart')

        # hash:存储登录用户购物车中添加的商品id和对应数量count
        cart_key = 'cart_%s' % user.id

        redis_conn.hincrby(cart_key, goods_id, count)
        # set：存储登录用户购物车中被勾选的商品id
        # cart_selected_key = 'cart_selected_%s' % user.id

        # if selected:
        #     redis_conn.sadd(cart_selected_key, goods_id)

        cart_dict = redis_conn.hgetall(cart_key)

        count_list = cart_dict.values()

        total_count = 0

        for count in count_list:

            total_count += 1

        return Response({"total_count": total_count}, status=status.HTTP_201_CREATED)
        # else:
        #     # 2.2 如果用户未登录，在cookie中保存未登录用户的购物车记录
        #     #获取原始cookie中购物车数据
        #     cookie_cart = request.COOKIES.get('cart')
        #     if cookie_cart:
        #         cart_dict=pickle.loads(base64.b64decode(cookie_cart.encode()))
        #     else:
        #         cart_dict={}
        #
        #     #在cookie购物车中保存用户添加的商品的id和对应数量count
        #     if goods_id in cart_dict:
        #         count += cart_dict[goods_id]['count']
        #
        #     #保存
        #     cart_dict[goods_id]={
        #         'count':count,
        #         'selected':selected
        #     }
        #     count_list = cookie_cart.keys()
        #     total_count = 0
        #     for count in count_list:
        #         total_count += 1
        #     # 3. 返回应答，购物车记录添加成功
        #     response = Response({'total_count':total_count},status=status.HTTP_201_CREATED)
        #     # 设置cookie购物车数据
        #     cart_data = base64.b64encode(pickle.dumps(cart_dict)).decode()  # str
        #     response.set_cookie('cart', cart_data, max_age=constants.CART_COOKIE_EXPIRES)
        #     return response

    # GET  /cart/
    def get(self, request):
        """
        查询购物车的数据
        1.获取用户购物车记录
        2.根据购物车记录中的商品的id获取对应商品的数据
        3.将购物车商品的数据序列化返回
        """

        try:

            user = request.user

        except Exception:

            user = None

        # h获取redis的链接
        redis_conn = get_redis_connection('cart')

        # 从redis hash中获取用户购物车中添加的商品 的id和对应的数量
        cart_key = "cart_%s" % user.id

        cart_dict = redis_conn.hgetall(cart_key)

        # 在redis set中获取用户购物车被勾选的商品的id
        cart_selected_key = 'cart_selected_%s' % user.id

        cart_selected_redis = redis_conn.smembers(cart_selected_key)
        # 组织数据

        cart = {}

        for goods_id, count in cart_dict.items():
            cart[int(goods_id)] = {

                'count': int(count),

                'selected': goods_id in cart_selected_redis
            }

        # 根据购物车记录中的商品的id获取对应的商品的数据
        goods_ids = cart.keys()

        goods = Goods.objects.filter(id__in=goods_ids)

        for good in goods:
            # 给good对象增加属性count和selected
            # 分别保存该商品在购物车添加的数量和勾选状态
            good.count = cart[good.id]['count']

            good.selected = cart[good.id]['selected']

        # 3.将购物车中的数据序列化返回
        serializer = CartGoodSerializer(goods, many=True)

        return Response(serializer.data)

    # PUT /cart/
    def put(self, request):
        """
        修改购物车中的数据
         1. 获取参数并进行校验(参数完整性，goods_id对应商品是否存在，count是否大于商品库存)
        2. 修改用户购物车中的数据
        3. 返回应答，修改成功
        """
        # 1. 获取参数并进行校验(参数完整性，goods_id对应商品是否存在，count是否大于商品库存)
        serializer = CartSerializer(data=request.data)

        serializer.is_valid(raise_exception=True)

        # 获取校验后的数据
        goods_id = serializer.validated_data['goods_id']

        count = serializer.validated_data['count']

        selected = serializer.validated_data['selected']

        # 获取user
        try:

            user = request.user

        except Exception:

            user = None

        # 2. 修改用户购物车中的数据
        # 获取redis链接
        redis_conn = get_redis_connection('cart')

        # 修改用户购物车中的对应商品的数量
        cart_key = "cart_%s" % user.id

        redis_conn.hset(cart_key, goods_id, count)

        # 修改用户购物车商品的勾选状态
        cart_selected_key = 'cart_selected_%s' % user.id

        if selected:
            # 勾选
            redis_conn.sadd(cart_selected_key, goods_id)
        else:
            # 取消勾选
            redis_conn.srem(cart_selected_key, goods_id)

        # 3. 返回应答，修改成功
        cart_dict = redis_conn.hgetall(cart_key)

        count_list = cart_dict.values()

        total_count = 0

        for count in count_list:
            total_count += 1

        return Response({"total_count": total_count})

    # DELETE /cart/
    def delete(self, request):
        """
         购物车记录删除:
        1. 获取sku_id并进行校验(sku_id必传，sku_id对应商品是否存在)
        2. 删除用户对应的购物车记录
        3. 返回应答，删除成功
        """
        # 1. 获取sku_id并进行校验(sku_id必传，sku_id对应商品是否存在)
        serializer = CartDelSerializer(data=request.data)

        serializer.is_valid(raise_exception=True)

        # 获取校验之后商品的id
        goods_id = serializer.validated_data['goods_id']

        try:

            user = request.user

        except Exception:

            user = None

        # 2. 删除用户对应的购物车记录
        if user and user.is_authenticated:
        # 获取redis链接
            redis_conn = get_redis_connection('cart')

            # 删除用户购物车中的对应商品的数量
            cart_key = "cart_%s" % user.id

            redis_conn.hdel(cart_key, goods_id)

            # 从redis set中移除sku_id勾选状态
            cart_selected_key = 'cart_selected_%s' % user.id

            redis_conn.srem(cart_selected_key, goods_id)

            # 3. 返回应答，删除成功
            cart_dict = redis_conn.hgetall(cart_key)

            count_list = cart_dict.values()

            total_count = 0

            for count in count_list:
                total_count += 1

            return Response({"total_count": total_count})

            # return Response(status=status.HTTP_204_NO_CONTENT)

# 获取购物车中的商品总数量
class CartCountView(APIView):
    """获取购物车中商品总数量"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        """获取购物车中商品总数量"""

        # 获取用户
        user = request.user

        # 获取redis链接
        redis_conn = get_redis_connection('cart')

        cart_key = "cart_%s" % user.id

        cart_dict = redis_conn.hgetall(cart_key)

        count_list = cart_dict.values()

        total_count = 0

        for count in count_list:
            print(count)
            total_count += 1

        print(total_count)

        return Response({'total_count': total_count})


